/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 2002, 2012 Oracle and/or its affiliates.  All rights reserved.
 *
 */

package persist.sqlapp;

import com.sleepycat.je.DatabaseException;
import com.sleepycat.persist.EntityCursor;
import com.sleepycat.persist.EntityIndex;
import com.sleepycat.persist.EntityJoin;
import com.sleepycat.persist.EntityStore;
import com.sleepycat.persist.ForwardCursor;
import com.sleepycat.persist.PrimaryIndex;
import com.sleepycat.persist.SecondaryIndex;

/**
 * The data accessor class for the entity model.
 * 
 * @author chao
 */
class RediusDao {
	/* Redius Accessors */
	PrimaryIndex<Integer, RediusLog> RediusByIp;
	SecondaryIndex<Integer, Integer, RediusLog> RediusByOnline;
	SecondaryIndex<Integer, Integer, RediusLog> RediusByOffline;
	SecondaryIndex<String, Integer, RediusLog> RediusById;

	/** Opens all primary and secondary indices. */
	public RediusDao(EntityStore store) throws DatabaseException {

		/* Primary index of the Employee database. */
		RediusByIp = store.getPrimaryIndex(Integer.class, RediusLog.class);

		/* Secondary index of the Employee database. */
		RediusByOnline = store.getSecondaryIndex(RediusByIp, Integer.class, "online");
		RediusByOffline = store.getSecondaryIndex(RediusByIp, Integer.class, "offline");
		RediusById = store.getSecondaryIndex(RediusByIp, String.class, "id");
	}

	/**
	 * Do prefix query, similar to the SQL statement: <blockquote>
	 * 
	 * <pre>
	 * SELECT * FROM table WHERE col LIKE 'prefix%';
	 * </pre>
	 * 
	 * </blockquote>
	 * 
	 * @param index
	 * @param prefix
	 * @return
	 * @throws DatabaseException
	 */
	public <V> EntityCursor<V> doPrefixQuery(EntityIndex<String, V> index,
			String prefix) throws DatabaseException {

		assert (index != null);
		assert (prefix.length() > 0);

		/* Opens a cursor for traversing entities in a key range. */
		char[] ca = prefix.toCharArray();
		final int lastCharIndex = ca.length - 1;
		ca[lastCharIndex]++;
		return doRangeQuery(index, prefix, true, String.valueOf(ca), false);
	}

	/**
	 * Do range query, similar to the SQL statement: <blockquote>
	 * 
	 * <pre>
	 * SELECT * FROM table WHERE col >= fromKey AND col <= toKey;
	 * </pre>
	 * 
	 * </blockquote>
	 * 
	 * @param index
	 * @param fromKey
	 * @param fromInclusive
	 * @param toKey
	 * @param toInclusive
	 * @return
	 * @throws DatabaseException
	 */
	public <K, V> EntityCursor<V> doRangeQuery(EntityIndex<K, V> index,
			K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)
			throws DatabaseException {

		assert (index != null);

		/* Opens a cursor for traversing entities in a key range. */
		return index.entities(fromKey, fromInclusive, toKey, toInclusive);
				
	}

	/**
	 * Do a "AND" join on a single primary database, similar to the SQL:
	 * <blockquote>
	 * 
	 * <pre>
	 * SELECT * FROM table WHERE col1 = key1 AND col2 = key2;
	 * </pre>
	 * 
	 * </blockquote>
	 * 
	 * @param pk
	 * @param sk1
	 * @param key1
	 * @param sk2
	 * @param key2
	 * @return
	 * @throws DatabaseException
	 */
	public <PK, SK1, SK2, E> ForwardCursor<E> doTwoConditionsJoin(
			PrimaryIndex<PK, E> pk, SecondaryIndex<SK1, PK, E> sk1, SK1 key1,
			SecondaryIndex<SK2, PK, E> sk2, SK2 key2) throws DatabaseException {

		assert (pk != null);
		assert (sk1 != null);
		assert (sk2 != null);

		EntityJoin<PK, E> join = new EntityJoin<PK, E>(pk);
		join.addCondition(sk1, key1);
		join.addCondition(sk2, key2);

		return join.entities();
	}


}
